package com.hexinfo.dmpro.sparing.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.file.FileAppender;
import cn.hutool.core.io.file.FileWriter;
import com.hexinfo.dmpro.common.model.MessageCenter;
import com.hexinfo.dmpro.common.service.MessageCenterService;
import com.hexinfo.dmpro.common.utils.ConnExecuteUtil;
import com.hexinfo.dmpro.common.utils.ScanCommonConstants;
import com.hexinfo.dmpro.component.comparison.entity.TableContrastParamEntity;
import com.hexinfo.dmpro.component.comparison.enums.TableContrastEnums;
import com.hexinfo.dmpro.sparing.model.HdfsHeatBackup;
import com.hexinfo.dmpro.sparing.service.ScriptExecTimeService;
import com.hexinfo.dmpro.sparing.service.ThreadPoolService;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.io.File;
import java.sql.Connection;
import java.sql.Statement;
import java.util.*;
/**
 * 脚本执行
 */
@Service
@Slf4j
public class ScriptExecTimeServiceImpl implements ScriptExecTimeService {

    @Value("${hdfs.heatBackup}")
    private String heatBackup;
    @Value("${hdfs.refreshTable}")
    private String refreshTable;
    @Value("${heatBackup.logPath}")
    private String logPath;

    @Autowired
    private MessageCenterService messageCenterService;

    @Autowired
    @Qualifier("connPoolHiveSource")
    private DataSource connPoolSource;

    @Autowired
    @Qualifier("connPoolHiveTarget")
    private DataSource connPoolTarget;

    /**
     * 按时间窗口热备比对
     */
    @Override
    @Async("threadPoolTaskExecutor")
    public void execShTime(List<HdfsHeatBackup> hdfsHeatBackups, String hiveSql,HdfsHeatBackup hdfsHeatBackupModel,
                           String strPath,String ss) {
        try {
            //插入日志文件缓存操作
            FileAppender appender = new FileAppender(new File(strPath), 100, true);
            MessageCenter messageCenter = addMessageCenter(ScanCommonConstants.ClusterName.HEATBACKUP.value
                    + ss + hdfsHeatBackupModel.getSourceName(), strPath);
            appender.append(appendLogStr(hdfsHeatBackupModel.getSourceName()
                    +"表【"+ss+"】distcp开始，HDFS地址个数："+hdfsHeatBackups.size()));
//            Connection connection =connPoolSource.getConnection();
//            //第一步：备份删表建表
//            int a = createTable(connection,hdfsHeatBackupModel.getBackupName(),hdfsHeatBackupModel.getSourceName());
//            if (connection != null && !connection.isClosed() && (a == 0 || a == 999)){
//                connection.close();
//            }
//            appender.append(appendLogStr(hdfsHeatBackupModel.getBackupName()+"备份表删表建表状态："+a));
            String str = "执行成功";
            for (HdfsHeatBackup hdfsHeatBackup : hdfsHeatBackups) {
                String shell = heatBackup+" "+hdfsHeatBackup.getSourceAddress() +" "+hdfsHeatBackup.getBackupAddress();
                String tarShell = heatBackup+" "+hdfsHeatBackup.getBackupAddress() +" "+hdfsHeatBackup.getTargetAddress();
                //第二步：备份库热备
                int b = ConnExecuteUtil.execShellCode(shell);
                appender.append(appendLogStr(hdfsHeatBackupModel.getSourceName()+"表热备到备份库结果："+b));
                //第三步：热备到目标地址
                int d = ConnExecuteUtil.execShellCode(tarShell);
                appender.append(appendLogStr(hdfsHeatBackupModel.getBackupName()+"表热备到目标库结果："+d));
                if (b != 0 || d != 0){
                    str = "执行失败";
                    appender.append(appendLogStr("时间窗口执行错误shell："+shell+"  执行结果："+b+"\n"+tarShell+"  执行结果："+d));
                    appendLogs(hdfsHeatBackup.getSourceData()+"/"+hdfsHeatBackup.getSourceData(),
                            "===========时间窗口执行错误shell："+shell+"  执行结果："+b+"\n"+tarShell+"  执行结果："+d);
                }
            }
            //第四步：刷新备份表
//            Connection connection1 =connPoolSource.getConnection();
//            int c = refreshTable(connection1, hdfsHeatBackupModel.getBackupName());
//            if (connection1 != null && !connection1.isClosed() && (c == 0 || c == 999)){
//                connection1.close();
//            }
//            appender.append(appendLogStr("刷新备份库表结果："+c));
//            //第五步：刷新目标表
//            int e = ConnExecuteUtil.execShellCode(refreshTable+" "+hdfsHeatBackupModel.getTargetName());
//            log.info("----------------"+hdfsHeatBackupModel.getBackupName()+"表建表、刷新表结果："+a+"、"+c+"、"+e);
//            appender.append(appendLogStr("刷新目标库表结果："+e));
            //修改执行状态
            messageCenter.setDataType(str);
            appender.append(appendLogStr("【HDFS文件热备"+str+"】"));
            updataMessageCenter(messageCenter);
            appender.flush();   //刷入文件中
//            //比对消息中心添加
//            String contrastPath = logPath.replace("{date}", DateUtil.format(DateUtil.date(), "yyyyMMdd"))
//                    +ScanCommonConstants.ClusterName.CONTRASTPATH.value+hdfsHeatBackupModel.getSourceName()+".txt";
//            appender.append(appendLogStr("【表数据比对开始】"));
//            MessageCenter messageCenter1 = addMessageCenter(ScanCommonConstants.ClusterName.CONTRAST.value
//                            + ss + hdfsHeatBackupModel.getSourceName(),contrastPath);
//            messageMap.put(TableContrastEnums.WARM.getValue()+"."+hdfsHeatBackupModel.getBackupName(),messageCenter1);
//            boolean bool = iTableContrastService.createTableContrastTask(createModelBackup(hdfsHeatBackupModel,hiveSql));
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 源删表建表
     * @return
     */
    private int createTable(Connection connection,String backupName,String sourceName) {

        try{
            String dropSql = "drop table if exists {backupName}";
            String createSql = "create table {backupName} like {sourceName}";
            String dropSql1 = dropSql.replace("{backupName}", backupName);
            String createSql1 = createSql.replace("{backupName}", backupName)
                    .replace("{sourceName}", sourceName);
            @Cleanup
            Statement st = connection.createStatement();
            int i1 = st.executeUpdate(dropSql1);
            int i = st.executeUpdate(createSql1);
            log.info("-----------时间窗口distcp前，备份库建"+backupName+"表成功------------");
            return i+i1;
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage());
            log.error("----------时间窗口distcp前，备份库建"+backupName+"表失败！！！！！！！");
            return 999;
        }
    }

    /**
     * 刷新备份表
     * @return
     */
    private int refreshTable(Connection connection,String name) {
        try{
            String sql = "msck repair table {tableName}";
            String dropSql1 = sql.replace("{tableName}", name);
            @Cleanup
            Statement st = connection.createStatement();
            int i = st.executeUpdate(dropSql1);
            log.info("------------刷新备份"+name+"表成功-----------");
            return i;
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage());
            log.error("-----------刷新备份"+name+"表失败！！！！！！！！");
            return 999;
        }
    }

    /**
     * 备份库与目标库比对信息
     * @param hdfsHeatBackup
     * @return
     */
    private TableContrastParamEntity createModelBackup(HdfsHeatBackup hdfsHeatBackup, String hiveSql) throws Exception{
        TableContrastParamEntity tableContrastParam = new TableContrastParamEntity();
        tableContrastParam.setContrastType(TableContrastEnums.WARM.getValue());
        tableContrastParam.setSourceDbName(hdfsHeatBackup.getBackupDbName());
        tableContrastParam.setSourceTableName(hdfsHeatBackup.getBackupTableName());
        tableContrastParam.setSourceQueryCriteria(hiveSql);
        tableContrastParam.setTargetDbName(hdfsHeatBackup.getTargetDbName());
        tableContrastParam.setTargetTableName(hdfsHeatBackup.getTargetTableName());
        tableContrastParam.setTargetQueryCriteria(hiveSql);
        return tableContrastParam;
    }

    /**
     * 消息中心表数据添加
     * @return
     */
    private MessageCenter addMessageCenter(String messageSub,String logPath) {
        MessageCenter messageCenter = new MessageCenter();
        messageCenter.setMenu("数据热备");
        messageCenter.setOperator("admin");
        messageCenter.setDataType("进行中");
        messageCenter.setMessageSubject(messageSub);
        messageCenter.setMessageWeight("1");
        messageCenter.setLogPath(logPath);
        messageCenterService.save(messageCenter);
        return messageCenter;
    }

    /**
     * 消息中心表数据修改
     * @return
     */
    private void updataMessageCenter(MessageCenter messageCenter) {
        messageCenterService.updateById(messageCenter);
    }

    /**
     * 热备日志追加进文件
     * @return
     */
    private void appendLog(String strPath,String str) {
        FileWriter writer = new FileWriter(strPath);
        writer.append("["+DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss")+"]"
                +str+"\n");
    }

    private String appendLogStr(String str) {
        return "["+DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss")+"]" +str;
    }

    public void appendLogs(String name,String str) {
        String strPath = logPath.replace("{date}", DateUtil.format(DateUtil.date(), "yyyyMMdd"))
                + name + ".txt";
        FileWriter writer = new FileWriter(strPath);
        writer.append("[" + DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss") + "]"
                + str + "\n");
    }

}